package sun.scheduler.core.job;

import sun.scheduler.core.ScheduleOptimizer;
import sun.scheduler.util.graph.algorithm.maxflow.EdgeFlow;

/**
 * Jobinfo used by the {@link ScheduleOptimizer} for the min cut computation and
 * modification of the duration.
 *
 * @author mfj
 */
public class LTCTInfo extends Process implements EdgeFlow
{

    /**
     * Gets the state of the calculation.
     */
    public final static Job.CurveState STATE = Job.CurveState.LTCT;
    /**
     * The current duaration of this job.
     */
    private long duration;
    /**
     * The current flow of this job.
     */
    private double flow;
    /**
     * The total ressources spend.
     */
    private double amountOfRessources;
    /**
     * The job which this flow computation belongs to.
     */
    public final Job baseJob;
    /**
     * The linear ratio cost per time.
     */
    public final double costRatio;
    /**
     * The ratio resources per time
     */
    public final double resourceRatio;

    /**
     * Instantiates a new {@link LTCTInfo} instance, from the given {@link Job}
     * with the specified initial duration.
     *
     * @param duration
     * @param baseJob
     */
    public LTCTInfo(Job baseJob)
    {
        this.baseJob = baseJob;

        // check if we have to setup the initial state for the LTCT
        double rRatio = baseJob.maxResources - baseJob.minResources;
        rRatio /= baseJob.minDuration - baseJob.maxDuration;
        this.resourceRatio = rRatio;

        double cRatio = baseJob.maxResources * baseJob.minDuration;
        cRatio -= baseJob.minResources * baseJob.maxDuration;
        cRatio /= baseJob.minDuration - baseJob.maxDuration;
        cRatio *= baseJob.resource.costPPT;
        this.costRatio = -cRatio;

        this.amountOfRessources = baseJob.minResources;
        this.duration = baseJob.maxDuration;
    }

    @Override
    public long getDuration()
    {
        return duration;
    }

    @Override
    double getAmountOfResources()
    {
        return amountOfRessources;
    }

    /**
     * Increases the duration by the specified delta and reduces the cost and
     * adjusts the amount of ressources
     *
     * @param delta the additional value to increase by
     */
    public void increaseDuration(long delta)
    {
        duration += delta;
        amountOfRessources += resourceRatio * delta;
    }

    @Override
    public void addFlow(double val)
    {
        flow += val;
    }

    @Override
    public double getFlow()
    {
        return flow;
    }

    @Override
    public double getLowerCapacity()
    {
        if (baseJob instanceof DummyJob)
            return 0;

        if (duration < baseJob.maxDuration)
            return costRatio;
        else
            return 0;
    }

    @Override
    public double getUpperCapacity()
    {
        if (baseJob instanceof DummyJob)
            return Double.MAX_VALUE;

        if (duration > baseJob.minDuration)
            return costRatio;
        else
            return Double.MAX_VALUE;
    }

}
